/*
	File:	physics/PhysicsContext.hpp
	Date:	2013-06-09
	Author:	Asteroth
*/


#ifndef __ZEN_PHYSICS_CONTEXT__
#define __ZEN_PHYSICS_CONTEXT__

#include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h>
#include <ptr.hpp>

#include "../math.hpp"
#include "../utils/BulletUtils.hpp"

namespace zen {

	namespace physics {

		class Physics;

		class PhysicsContext {

		public:

			PhysicsContext();
			~PhysicsContext();

			bool update(int interval);
			bool debugDraw();

			void setGravity(const glm::vec3 &gravity);

			bool addRigidBody(btRigidBody* body);
			bool addStaticPlane(const glm::mat4 &view, const float &originDistance, const glm::vec3 &normal);
			bool addBox(const glm::mat4 &view, const glm::vec3 &halfExtents);

			
		private:

			friend class Physics;
			int										id;
			btBroadphaseInterface*                  broadphase;
			btDefaultCollisionConfiguration*        collisionConfiguration;
			btCollisionDispatcher*                  collisionDispatcher;
			btSequentialImpulseConstraintSolver*    constraintSolver;
			btDiscreteDynamicsWorld*                dynamicsWorld;

		};

		typedef ptr(PhysicsContext) PPhysicsContext;

		

		inline bool PhysicsContext::update(int interval) {
			dynamicsWorld->stepSimulation(interval / 1000.0f, 10);
			dynamicsWorld->clearForces();
			return true;
		}

		inline bool PhysicsContext::debugDraw() {
			dynamicsWorld->debugDrawWorld();
			return true;
		}

		inline void PhysicsContext::setGravity(const glm::vec3 &gravity) {
			dynamicsWorld->setGravity(zen::utils::BulletConvert::toBtVector3(gravity));
		}

		inline bool PhysicsContext::addRigidBody(btRigidBody* body) {
			dynamicsWorld->addRigidBody(body);
			return true;
		}


	} // namespace physics

} // namespace zen

#endif // __ZEN_PHYSICS_CONTEXT__
